package com.yzs.base.base

import android.os.Bundle
import android.util.Log
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.*
import androidx.viewbinding.ViewBinding
import com.alibaba.android.arouter.launcher.ARouter
import com.gyf.immersionbar.ImmersionBar
import com.jeremyliao.liveeventbus.core.Observable
import com.yzs.base.ui.dialog.LoadingDialog
import java.util.concurrent.atomic.AtomicBoolean

/**
 *    author : yzs
 *    date   : 2022/1/1211:50
 *    desc   : 基础类封装
 */
abstract class BaseActivity : AppCompatActivity() {
    private val TAG = this.javaClass.simpleName

    protected lateinit var mView: View

    private val visibleAtomic = AtomicBoolean(false)

    private var mLoadingDialog: LoadingDialog? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.d(TAG, "BaseActivity-- ${this.javaClass.name} onCreate()")
        before()
        mView = initViewBinding()?.root ?: layoutInflater.inflate(getLayoutId(), null)
        setContentView(mView)
        // 页面进入设状态栏样色
        statusBarDarkFont(true)
        // 注册 ARouter
        ARouter.getInstance().inject(this)
        // vm
        initViewModel()
        // 初始化 View
        init(savedInstanceState)
        // 观察数据响应
        observe()
        // 点击事件监听
        onClick()
        // 进入页面 第一次加载数据
        loadData()
    }

    override fun onResume() {
        super.onResume()
        visibleAtomic.set(true)
        Log.d(TAG, "BaseActivity-- ${this.javaClass.name} onResume()")
        onVisible()
    }

    override fun onPause() {
        super.onPause()
        visibleAtomic.set(false)
        Log.d(TAG, "BaseActivity-- ${this.javaClass.name} onPause()")
        onHidden()
    }

    override fun onStop() {
        super.onStop()
        Log.d(TAG, "BaseActivity-- ${this.javaClass.name} onStop()")
    }

    override fun onDestroy() {
        visibleAtomic.set(false)
        dismissLoadingDialog()
        mLoadingDialog = null
        super.onDestroy()
    }

    protected fun showLoadingDialog(canCancel: Boolean = false) {
        if (this.isFinishing) return
        if (mLoadingDialog == null) mLoadingDialog = LoadingDialog(this, canCancel)
        mLoadingDialog?.let { if (!it.isShowing) it.show() }
    }

    protected open fun dismissLoadingDialog() {
        mLoadingDialog?.let { if (it.isShowing) it.dismiss() }
    }

    open fun before() {
    }

    /**
     * 使用 viewBinding 初始布局
     */
    open fun initViewBinding(): ViewBinding? {
        return null
    }

    /**
     * activity入口
     */
    abstract fun init(savedInstanceState: Bundle?)

    /**
     * 获取layout布局
     */
    abstract fun getLayoutId(): Int


    /**
     * 初始化 viewModel
     * 之所以没有设计为抽象，是因为部分简单 activity 可能不需要 viewModel
     * observe 同理
     */
    open fun initViewModel() {}

    /**
     * 注册观察者
     */
    open fun observe() {}

    /**
     * 加载数据
     */
    open fun loadData() {}

    /**
     * 点击事件
     */
    open fun onClick() {}

    /**
     * 可交互时回调 （和 fragment 保持方法一直）
     */
    open fun onVisible() {}

    /**
     * 不可交互时回调 （和 fragment 保持方法一直）
     */
    open fun onHidden() {}

    /**
     * 通过 activity 获取 viewModel，跟随 activity 生命周期
     */
    fun <T : ViewModel> getActivityViewModel(modelClass: Class<T>): T {
        return ViewModelProvider(this, defaultViewModelProviderFactory).get(modelClass)
    }

    /**
     * 扩展用于liveData便捷写法的函数
     * [block] liveData 对象，响应 change 变化的逻辑块
     */
    protected inline fun <T : Any> LiveData<T>.observeKt(crossinline block: (T?) -> Unit) {
        this.observe(this@BaseActivity, Observer { block(it) })
    }

    /**
     * 扩展用于 liveData 便捷写法的函数
     * [block] liveData 对象，响应 change 变化的逻辑块
     * 认为 不为 null 的情况
     */
    protected inline fun <T : Any> LiveData<T>.observeKtNoNull(crossinline block: (T) -> Unit) {
        this.observe(this@BaseActivity, Observer { block(it) })
    }

    protected inline fun <T> Observable<T>.register(crossinline block: (T) -> Unit) {
        this.observe(this@BaseActivity, { block(it) })
    }

    /**
     * 如果之前有消息发送，可以在注册时收到消息（消息同步）
     */
    protected inline fun <T> Observable<T>.registerSticky(crossinline block: (T) -> Unit) {
        this.observeSticky(this@BaseActivity, { block(it) })
    }

    /**
     * 设置状态栏字体颜色
     * [isDarkFont] true:深色  false:浅色
     */
    protected fun statusBarDarkFont(isDarkFont: Boolean) {
        ImmersionBar.with(this).statusBarDarkFont(isDarkFont).init()
    }

    /**
     * 判断页面是否正在可见
     */
    protected fun isPageVisible(): Boolean {
        return visibleAtomic.get()
    }
}